package com.qianxun.modular.doc.common;

import com.alibaba.fastjson.JSON;
import com.github.junrar.Archive;
import com.github.junrar.rarfile.FileHeader;
import com.qianxun.modular.doc.entity.Doc;
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
import org.apache.commons.lang3.StringUtils;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Zip;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.tar.TarEntry;
import org.apache.tools.tar.TarInputStream;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.channels.FileChannel;
import java.util.*;
import java.util.zip.GZIPInputStream;

/**
 * 文档默认处理类
 *
 * @author Admin
 */
public abstract class AbstractDocBaseService {
    @Value("${spring.resources.static-locations}")
    protected String containerRootPath;

    /**
     * 获取文件系统根目录
     *
     * @return
     */
    protected String getOuterRootName() {
        return containerRootPath.split(",")[1].substring("file:".length());
    }

    /**
     * 临时文件目录（下载打包时临时缓存目录）
     */
    @Value("${tmp-path}")
    private String tmpPath;

    /**
     * 压缩文件临时目录
     */
    private String zipTmpPath = tmpPath + File.separator + "zip";

    /**
     * 搜索文件列表
     *
     * @param folder  文件目录
     * @param keyword 关键词
     * @return
     */
    protected List<File> searchFiles(File folder, String keyword) {
        List<File> result = new ArrayList<File>();
        if (folder.isFile()) {
            result.add(folder);
        }

        File[] subFolders = folder.listFiles(new FileFilter() {
            @Override
            public boolean accept(File file) {
                if (file.isDirectory()) {
                    return true;
                }
                if (file.getName().toLowerCase().contains(keyword)) {
                    return true;
                }
                return false;
            }
        });

        if (subFolders != null) {
            for (File file : subFolders) {
                if (file.isFile()) {
                    // 如果是文件则将文件添加到结果列表中
                    result.add(file);
                } else {
                    // 如果是文件夹，则递归调用本方法，然后把所有的文件加到结果列表中
                    result.addAll(searchFiles(file, keyword));
                }
            }
        }
        return result;
    }

    /**
     * 输出到网页显示
     *
     * @param localParentPath 本地文件路径
     * @param map
     * @param response
     * @param request
     * @param deleteEnable    是否删除
     * @throws Exception
     */
    protected void sendTargetToWebPage(String localParentPath, Map map, HttpServletResponse response, HttpServletRequest request, boolean deleteEnable) throws Exception {
        File localEntry = new File(localParentPath);
        if (false == localEntry.exists()) {
            map.put("msg", "文件 " + localParentPath + " 不存在！");
            writeJson(map, response);
            return;
        }
        String targetName = localEntry.getName();
        //Send the file to webPage
        sendFileToWebPage(localParentPath, targetName, response, request);

        if (deleteEnable) {
            //Delete target file or dir
            delFileOrDir(localParentPath);
        }
    }

    /**
     * 网页展示文件
     *
     * @param localParentPath 本地文件路径
     * @param file_name       文件名称
     * @param response
     * @param request
     * @throws Exception
     */
    protected void sendFileToWebPage(String localParentPath, String file_name, HttpServletResponse response, HttpServletRequest request) throws Exception {

        String dstPath = localParentPath;
        System.out.println("sendFileToWebPage() file_name befor convert:" + file_name);

        //解决中文编码问题
        String userAgent = request.getHeader("User-Agent").toUpperCase();
        if (userAgent.indexOf("MSIE") > 0 || userAgent.indexOf("LIKE GECKO") > 0)    //LIKE GECKO is for IE10
        {
            file_name = URLEncoder.encode(file_name, "UTF-8");
            System.out.println("sendFileToWebPage() file_name after URL Encode:" + file_name);
        } else {
            file_name = new String(file_name.getBytes("UTF-8"), "ISO8859-1");


            System.out.println("sendFileToWebPage() file_name after convert to ISO8859-1:" + file_name);
        }
        //解决空格问题（空格变加号和兼容性问题）
        file_name = file_name.replaceAll("\\+", "%20").replaceAll("%28", "\\(").replaceAll("%29", "\\)").replaceAll("%3B", ";").replaceAll("%40", "@").replaceAll("%23", "\\#").replaceAll("%26", "\\&");
        System.out.println("sendFileToWebPage() file_name:" + file_name);

        response.setHeader("content-disposition", "attachment;filename=\"" + file_name + "\"");

        //读取要下载的文件，保存到文件输入流
        FileInputStream in = null;
        //创建输出流
        OutputStream out = null;
        try {
            //读取要下载的文件，保存到文件输入流
            in = new FileInputStream(dstPath);
            //创建输出流
            out = response.getOutputStream();
            //创建缓冲区
            byte buffer[] = new byte[1024];
            int len = 0;
            //循环将输入流中的内容读取到缓冲区当中
            while ((len = in.read(buffer)) > 0) {
                //输出缓冲区的内容到浏览器，实现文件下载
                out.write(buffer, 0, len);
            }

            in.close();
            in = null;
            out.close();
            out = null;
        } catch (Exception e) {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
            e.printStackTrace();
            System.out.println("sendFileToWebPage() Exception");
        }
    }


    /**
     * 删除文件或者文件夹
     *
     * @param path 文件、文件夹路径
     * @return
     */
    protected static boolean delFileOrDir(String path) {
        File file = new File(path);
        if (file.exists()) {
            if (file.isDirectory()) {
                File[] tmp = file.listFiles();
                for (int i = 0; i < tmp.length; i++) {
                    String subDirPath = path + "/" + tmp[i].getName();
                    if (delFileOrDir(subDirPath) == false) {
                        System.out.println("delFileOrDir() delete subDir Failed:" + subDirPath);
                        return false;
                    }
                }
            }

            if (file.delete() == false) {
                System.out.println("delFileOrDir() delete Dir Failed:" + path);
                return false;
            }
        }
        return true;
    }

    /**
     * 将指定内容写出为json格式
     *
     * @param obj
     * @param response
     */
    protected void writeJson(Object obj, HttpServletResponse response) {

        try {
            response.setCharacterEncoding("UTF-8");
            String json = JSON.toJSONStringWithDateFormat(obj, "yyy-MM-dd HH:mm:ss");
            PrintWriter pw = response.getWriter();
            response.setContentType("application/javascript");
            pw.write(json);
            pw.flush();
            pw.close();
        } catch (IOException e) {
            System.out.println("BaseController>writeJson  ERROR!");
            e.printStackTrace();
        }

    }

    /**
     * 获取文件后缀名
     *
     * @param filePath 文件全路径
     * @return
     */
    protected static String getFileSuffix(String filePath) {
        String suffix = filePath.substring(filePath.lastIndexOf(".") + 1);
        return suffix.toLowerCase();
    }

    /**
     * 是否是文件类型
     *
     * @param fileSuffix 文件后缀
     * @return
     */
    protected static boolean isText(String fileSuffix) {
        if (fileSuffix == null) {
            //"未知文件类型"
            return false;
        }

        switch (fileSuffix) {
            case "txt":
            case "log":
            case "md":
            case "py":
            case "java":
            case "cpp":
            case "hpp":
            case "c":
            case "h":
            case "json":
            case "xml":
            case "html":
            case "sql":
            case "js":
            case "css":
            case "jsp":
            case "php":
            case "properties":
            case "conf":
            case "out":
            case "sh":
            case "bat":
            case "msg":
            case "cmake":
                return true;
            default:
                break;
        }
        return false;
    }

    protected static boolean isOffice(String fileSuffix) {
        if (fileSuffix == null) {
            //"未知文件类型"
            return false;
        }

        switch (fileSuffix) {
            case "doc":
            case "docx":
            case "xls":
            case "xlsx":
            case "ppt":
            case "pptx":
                return true;
            default:
                break;
        }
        return false;
    }

    protected boolean isPdf(String fileSuffix) {
        if (fileSuffix == null) {
            //"未知文件类型"
            return false;
        }

        switch (fileSuffix) {
            case "pdf":
                return true;
            default:
                break;
        }
        return false;
    }

    /**
     * 获取文件内容
     *
     * @param path               文件路径
     * @param encodeDetectEnable
     * @return
     */
    protected static String readDocContentFromFile(String path, boolean encodeDetectEnable) {
        String filePath = path;
        try {
            File file = new File(filePath);
            if (!file.exists() || !file.isFile()) {
                return null;
            }

            int fileSize = (int) file.length();
            if (fileSize <= 0) {
                return null;
            }

            String encode = null;

            byte buffer[] = new byte[fileSize];
            FileInputStream in;
            in = new FileInputStream(filePath);
            in.read(buffer, 0, fileSize);
            in.close();

            String content = null;
            if (encodeDetectEnable) {
                //encode = getEncodeOfBuffer(buffer, fileSize);
                encode = getCharset(filePath);
                System.out.println("readDocContentFromFile " + filePath + " encode:" + encode);
            }
            if (encode == null) {
                content = new String(buffer);
            } else {
                content = new String(buffer, encode);
            }
            return content;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 保存文件内容
     *
     * @param content 内容信息
     * @param path    文件路径
     * @param encode  编码
     * @return
     */
    protected static boolean saveDocContentToFile(String content, String path, String encode) {
        if (content == null) {
            System.out.println("saveDocContentToFile() content is null");
            return false;
        }

        File folder = new File(path);
        if (!folder.exists()) {
            //System.out.println("saveDocContentToFile() path:" + path + " not exists!");
            if (folder.mkdirs() == false) {
                System.out.println("saveDocContentToFile() mkdir path:" + path + " Failed!");
                return false;
            }
        }

        //创建文件输入流
        String filePath = path;
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(filePath);
        } catch (FileNotFoundException e) {
            System.out.println("saveVirtualDocContent() new FileOutputStream failed");
            e.printStackTrace();
            return false;
        }
        try {
            byte[] buff = null;
            System.out.println("saveDocContentToFile " + path + " encode:" + encode);

            if (encode == null) {
                buff = content.getBytes();
            } else {
                buff = content.getBytes(encode); //将String转成指定charset的字节内容
            }

            out.write(buff, 0, buff.length);
            //关闭输出流
            out.close();
        } catch (IOException e) {
            System.out.println("saveDocContentToFile() out.write exception");
            e.printStackTrace();
            return false;
        }
        return true;

    }

    /**
     * 获取文件的编码
     *
     * @param path 文件路径
     * @return
     */
    protected static String getCharset(String path) {
        String charset = "GBK";
        byte[] first3Bytes = new byte[3];
        try {
            boolean checked = false;
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path));
            bis.mark(0); // 注： bis.mark(0);修改为 bis.mark(100);我用过这段代码，需要修改上面标出的地方。
            // 注：不过暂时使用正常，遂不改之
            int read = bis.read(first3Bytes, 0, 3);
            if (read == -1) {
                bis.close();
                return charset; // 文件编码为 ANSI
            } else if (first3Bytes[0] == (byte) 0xFF && first3Bytes[1] == (byte) 0xFE) {
                charset = "UTF-16LE"; // 文件编码为 Unicode
                checked = true;
            } else if (first3Bytes[0] == (byte) 0xFE && first3Bytes[1] == (byte) 0xFF) {
                charset = "UTF-16BE"; // 文件编码为 Unicode big endian
                checked = true;
            } else if (first3Bytes[0] == (byte) 0xEF && first3Bytes[1] == (byte) 0xBB && first3Bytes[2] == (byte) 0xBF) {
                charset = "UTF-8"; // 文件编码为 UTF-8
                checked = true;
            }
            bis.reset();
            if (!checked) {
                while ((read = bis.read()) != -1) {
                    if (read >= 0xF0)
                        break;
                    if (0x80 <= read && read <= 0xBF) // 单独出现BF以下的，也算是GBK
                        break;
                    if (0xC0 <= read && read <= 0xDF) {
                        read = bis.read();
                        if (0x80 <= read && read <= 0xBF) // 双字节 (0xC0 - 0xDF)
                            // (0x80 - 0xBF),也可能在GB编码内
                            continue;
                        else
                            break;
                    } else if (0xE0 <= read && read <= 0xEF) { // 也有可能出错，但是几率较小
                        read = bis.read();
                        if (0x80 <= read && read <= 0xBF) {
                            read = bis.read();
                            if (0x80 <= read && read <= 0xBF) {
                                charset = "UTF-8";
                                break;
                            } else
                                break;
                        } else
                            break;
                    }
                }
            }
            bis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("charset:" + charset);
        return charset;
    }

    /**
     * 创建文件或者文件夹
     *
     * @param doc 文件信息
     * @return
     */
    protected boolean createRealDoc(Doc doc) {
        String name = doc.getName();
        int type = doc.getType();
        //获取 doc parentPath
        String localDocPath = doc.getPath();
        if (type == 2) //目录
        {
            if (false == createDir(localDocPath + File.separator + name)) {
                return false;
            }
        } else {
            if (false == createFile(localDocPath, name)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 创建文件夹
     *
     * @param path 文件夹名称
     * @return
     */
    protected boolean createDir(String path) {
        File dir = new File(path);
        if (!dir.exists()) {
            return dir.mkdirs();
        } else {
            return true;
        }
    }

    /**
     * 创建文件
     *
     * @param path     文件保存路径
     * @param filename 文件名称
     * @return
     */
    protected static boolean createFile(String path, String filename) {
        File dir = new File(path);
        if (!dir.exists()) {
            if (dir.mkdirs() == false) {
                return false;
            }
        }

        File file = new File(path + "/" + filename);
        if (!file.exists()) {
            try {
                return file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
        } else {
            return true;
        }
    }

    /**
     * 更新文件信息
     *
     * @param doc
     * @param uploadFile
     * @param chunkNum
     * @param chunkSize
     * @param chunkParentPath
     * @return
     */
    protected boolean updateRealDoc(Doc doc, MultipartFile uploadFile, Integer chunkNum, Long chunkSize, String
            chunkParentPath) {
        String parentPath = doc.getPath();
        String name = doc.getName();

        String localDocParentPath = parentPath;
        String retName = null;
        try {
            retName = saveFile(doc, uploadFile, localDocParentPath, name);
        } catch (Exception e) {
            System.out.println("updateRealDoc() saveFile " + name + " 异常！");
            e.printStackTrace();
            return false;
        }

        System.out.println("updateRealDoc() saveFile return: " + retName);
        if (retName == null || !retName.equals(name)) {
            System.out.println("updateRealDoc() saveFile " + name + " Failed！");
            return false;
        }
        return true;
    }

    /**
     * 保存文件信息
     *
     * @param doc
     * @param srcFile
     * @param path
     * @param fileName
     * @return
     * @throws Exception
     */
    protected String saveFile(Doc doc, MultipartFile srcFile, String path, String fileName) throws Exception {
        if (fileName == null || "".equals(fileName)) {
            System.out.println("saveFile() fileName is empty!");
            return null;
        }

        doc.setType(1);

        File dstFile = new File(path, fileName);
        doc.setPath(dstFile.getPath());
        //底层接口不能主动创建上层目录，不存在上层目录则直接报错
        File forder1 = new File(path);
        if (!forder1.exists()) {
            System.out.println("saveFile() path:" + path + " not exists!");
            forder1.mkdirs(); //创建目录
            String name = forder1.getName();
            doc.setName(name);
            doc.setType(2);
            doc.setPath(forder1.getPath());
        }
        saveFile(srcFile.getInputStream(), dstFile);

        return fileName;
    }

    /**
     * 文件保存
     *
     * @param is
     * @param dest
     */
    protected void saveFile(InputStream is, File dest) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(dest);
            int len;
            byte[] buffer = new byte[1024];
            while ((len = is.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fos != null) {
                    fos.close();
                }
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

    protected static boolean copyFile(String srcFilePath, String dstFilePath, boolean cover) {
        File srcFile = new File(srcFilePath);
        if (srcFile.exists() == false) {
            System.err.println("copyFile() srcFilePath:" + srcFilePath + " not exists!");
            return false;
        }

        File dstFile = new File(dstFilePath);
        if (cover == false && dstFile.exists()) {
            //不允许覆盖
            System.err.println("copyFile() " + dstFilePath + " exists!");
            return false;
        }

        boolean ret = false;
        FileInputStream in = null;
        FileOutputStream out = null;
        FileChannel inputChannel = null;
        FileChannel outputChannel = null;

        try {
            //Copy by Channel
            in = new FileInputStream(srcFilePath);
            out = new FileOutputStream(dstFilePath);
            inputChannel = in.getChannel();
            outputChannel = out.getChannel();
            outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
            inputChannel.close();
            outputChannel.close();
            in.close();
            out.close();
            ret = true;
        } catch (Exception e) {
            System.err.println("copyFile() from " + srcFilePath + " to " + dstFilePath + " Exception");
            e.printStackTrace();
        } finally {
            try {
                if (inputChannel != null) {
                    inputChannel.close();
                }
                if (outputChannel != null) {
                    outputChannel.close();
                }
                if (in != null) {
                    in.close();
                }
                if (out != null) {
                    out.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        return ret;
    }

    protected String combineChunks(String targetParentPath, String fileName, Integer chunkNum, String chunkParentPath) {
        try {
            String targetFilePath = targetParentPath + fileName;
            FileOutputStream out;

            out = new FileOutputStream(targetFilePath);
            FileChannel outputChannel = out.getChannel();

            long offset = 0;
            for (int chunkIndex = 0; chunkIndex < chunkNum; chunkIndex++) {
                String chunkFilePath = chunkParentPath + fileName + "_" + chunkIndex;
                FileInputStream in = new FileInputStream(chunkFilePath);
                FileChannel inputChannel = in.getChannel();
                outputChannel.transferFrom(inputChannel, offset, inputChannel.size());
                offset += inputChannel.size();
                inputChannel.close();
                in.close();
            }
            outputChannel.close();
            out.close();
            return fileName;
        } catch (Exception e) {
            System.out.println("combineChunks() Failed to combine the chunks");
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 待下载文件处理
     * 对基本文件返回下载信息
     * 对文件夹进行压缩后返回
     *
     * @param doc 待处理的文件
     * @return
     */
    protected Map downloadDocPrepare_FSM(Doc doc) {
        Map map = new HashMap();
        map.put("status", true);
        map.put("code", 200);
        File file = new File(doc.getPath());
        if (file.exists()) {
            String targetName = doc.getName();
            String targetPath = doc.getPath();
            if (doc.getType() == 1) {
                Doc downloadDoc = buildDownloadDocInfo(targetPath, targetName);
                map.put("data", downloadDoc);
                map.put("msgDaTa", 0);
                return map;
            } else if (doc.getType() == 2) {
                if (!isEmptyDir(doc.getPath(), true)) {
                    //doCompressDir and save the zip File under userTmpDir
                    targetName = doc.getName() + ".zip";
                    if (doCompressDir(doc.getPath(), tmpPath, targetName)) {
                        Doc downloadDoc = buildDownloadDocInfo(tmpPath + File.separator + targetName, targetName);
                        map.put("data", downloadDoc);
                        map.put("msgDaTa", 1);
                        return map;
                    }
                }
            }
        }
        return map;

    }

    /**
     * 构建文件加密 名称和路径
     *
     * @param targetPath
     * @param targetName
     * @return
     */
    protected Doc buildDownloadDocInfo(String targetPath, String targetName) {
        String encTargetName = base64EncodeURLSafe(targetName);
        if (encTargetName == null) {
            return null;
        }
        String encTargetPath = base64EncodeURLSafe(targetPath);
        if (encTargetPath == null) {
            return null;
        }

        Doc doc = new Doc();
        doc.setPath(encTargetPath);
        doc.setName(encTargetName);
        return doc;
    }

    /**
     * 加密
     *
     * @param str
     * @return
     */
    protected String base64EncodeURLSafe(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }

        try {
            byte[] textByte = str.getBytes("UTF-8");
            //编码
            String base64Str = Base64.getEncoder().encodeToString(textByte);
            return base64Str;
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 解密
     *
     * @param base64Str
     * @return
     */
    protected String base64Decode(String base64Str) {
        byte[] data = Base64.getDecoder().decode(base64Str);
        try {
            String str = new String(data, "UTF-8");
            return str;
        } catch (UnsupportedEncodingException e) {
            System.out.println("base64Decode new String Error");
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 是否是空目录
     * true there is not file and dir, false: there is no file
     *
     * @param dirPath
     * @param strict
     * @return
     */
    protected boolean isEmptyDir(String dirPath, boolean strict) {
        File dir = new File(dirPath);
        if (isEmptyDir(dir, strict) == true) {
            return true;
        }
        return false;
    }

    /**
     * 是否是空目录
     * true there is not file and dir, false: there is no file
     *
     * @param dir    目录文件
     * @param strict
     * @return
     */
    protected boolean isEmptyDir(File dir, boolean strict) {
        if (!dir.exists()) {
            return true;
        }

        File[] fileList = dir.listFiles();
        if (fileList != null && fileList.length > 0) {
            if (strict) {
                return false;
            }

            for (int i = 0; i < fileList.length; i++) {
                if (fileList[i].isFile()) {
                    return false;
                }
                if (isEmptyDir(fileList[i], strict) == false) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 执行文件压缩
     *
     * @param srcParentPath
     * @param tmpPath
     * @param dstParentPath
     * @return
     */
    protected boolean doCompressDir(String srcParentPath, String tmpPath, String dstParentPath) {

        //if dstDir not exists create it
        File dstDir = new File(tmpPath);
        if (!dstDir.exists()) {
            if (createDir(tmpPath) == false) {
                return false;
            }
        }
        //开始压缩
        if (compressExe(srcParentPath, tmpPath + File.separator + dstParentPath) == true) {
            System.out.println("压缩完成！");
        } else {
            System.out.println("doCompressDir()  压缩失败！");
            return false;
        }

        return true;
    }

    /**
     * 文件压缩
     *
     * @param srcPathName
     * @param finalFile
     * @return
     */
    protected boolean compressExe(String srcPathName, String finalFile) {
        File zipFile = new File(finalFile);    //finalFile

        File srcdir = new File(srcPathName); //srcFile or Dir
        if (!srcdir.exists()) {
            System.out.println(srcPathName + "不存在！");
            return false;
        }

        Project prj = new Project();
        Zip zip = new Zip();
        zip.setProject(prj);
        zip.setDestFile(zipFile);
        FileSet fileSet = new FileSet();
        fileSet.setProject(prj);
        fileSet.setDir(srcdir);
        //fileSet.setIncludes("**/*.java"); //包括哪些文件或文件夹 eg:zip.setIncludes("*.java");
        //fileSet.setExcludes(...); //排除哪些文件或文件夹
        zip.addFileset(fileSet);

        //windows下设置
        zip.setEncoding("GBK");
        zip.execute();

        if (zipFile.exists()) {
            return true;
        }
        return false;
    }

    /**
     * 文件列表排序处理
     *
     * @param docList 待排序的文件列表
     * @param sort    排序规则
     * @return
     */
    protected List<Doc> sortDocList(List<Doc> docList, String sort) {
        Collections.sort(docList,
                new Comparator<Doc>() {
                    HashMap<Integer, String> sortMap = buildSortMap(sort);

                    @Override
                    public int compare(Doc u1, Doc u2) {
                        long diff = getSortDiff(u1, u2, sortMap);    //
                        if (diff > 0) {
                            return 1;
                        } else if (diff < 0) {
                            return -1;
                        }
                        return 0;
                    }

                    private long getSortDiff(Doc u1, Doc u2, HashMap<Integer, String> sortMap) {
                        long diff = 0;
                        for (int i = 0; i < sortMap.size(); i++) {
                            String sortType = sortMap.get(i);
                            System.out.println("sortType:" + sortType);
                            if (sortType != null) {
                                diff = getSortDiffBySortType(u1, u2, sortType);
                                if (diff != 0) {
                                    return diff;
                                }
                            }
                        }
                        return diff;
                    }

                    private long getSortDiffBySortType(Doc u1, Doc u2, String sortType) {
                        switch (sortType) {
                            case "type":
                                return u1.getType() - u2.getType();
                            case "typeR":
                                return u2.getType() - u1.getType();
                            case "name":
                                return u1.getName().compareTo(u2.getName());
                            case "nameR":
                                return u2.getName().compareTo(u1.getName());
                            case "size":
                                return u1.getSize() - u2.getSize();
                            case "sizeR":
                                return u2.getSize() - u1.getSize();
                            case "modifyTime":
                                return u1.getLatestEditTime() - u2.getLatestEditTime();
                            case "modifyTimeR":
                                return u2.getLatestEditTime() - u1.getLatestEditTime();
                            case "createTime":
                                return u1.getCreateTime() - u2.getCreateTime();
                            case "createTimeR":
                                return u2.getCreateTime() - u1.getCreateTime();
                        }
                        return 0;
                    }

                    private HashMap<Integer, String> buildSortMap(String sort) {
                        String[] sortStrs = sort.split(" ");
                        HashMap<Integer, String> sortMap = new HashMap<Integer, String>();
                        for (int i = 0; i < sortStrs.length; i++) {
                            String sortStr = sortStrs[i];
                            //System.out.println("sortStr:" + sortStr);
                            if (sortStr != null && !sortStr.isEmpty()) {
                                sortMap.put(i, sortStr);
                            }
                        }

                        return sortMap;
                    }
                }
        );

        return docList;
    }

    /**
     * 处理文件列表信息参数
     *
     * @param dir 目录
     * @param pid 父ID
     * @return
     */
    protected List<Doc> commonDealFileList(File dir, String pid) {
        List<Doc> result = new ArrayList<>();
        File[] files = dir.listFiles();

        for (File file : files) {
            Doc doc = new Doc();
            int type = 1;
            if (file.isDirectory()) {
                type = 2;
            }
            String subDocParentPath = dir.getPath() + File.separator + file.getName();
            doc.setPath(subDocParentPath);
            String id = buildDocIdByName(doc.getPath());
            doc.setId(id);
            long size = file.length();
            String name = file.getName();
            String[] temp = new String[2];
            seperatePathAndName(doc.getPath(), temp);
            doc.setPid(buildDocIdByName(temp[0]));
            doc.setType(type);
            doc.setSize(size);
            doc.setName(name);
            doc.setLatestEditTime(file.lastModified());
            doc.setCreateTime(file.lastModified());
            String filePath = file.getPath();
            String outerRootName = getOuterRootName().replace("/", "\\");
            String replace = filePath.replace(outerRootName, "");
            doc.setViewPath(replace);
            result.add(doc);
        }
        return result;
    }

    /**
     * 构建文件ID
     * 通过文件全路径的哈希值进行构建
     *
     * @param parentPath 文件路径
     * @return
     */
    protected String buildDocIdByName(String parentPath) {
        String temp = parentPath.replace("/", "_").replace("\\", "_");
        String outerRootName = getOuterRootName().replace("/", "_").replace("\\", "_");
        if (temp.equals(outerRootName)) {
            return "0";
        }
        Long docId = parentPath.hashCode() + 102147483647L;
        return String.valueOf(docId);
    }

    /**
     * 分割文件路径和文件名称
     *
     * @param entryPath 待分割的原始路径
     * @param result    结果数组
     * @return
     */
    protected int seperatePathAndName(String entryPath, String[] result) {
        seperatePathAndName(entryPath, result, "/");
        if (StringUtils.isBlank(result[0])) {
            seperatePathAndName(entryPath, result, "\\\\");
        }
        return 0;
    }

    /**
     * 分割文件路径和文件名称
     *
     * @param entryPath 待分割的原始路径
     * @param result    结果数组
     * @param regex     分隔符
     * @return
     */
    protected int seperatePathAndName(String entryPath, String[] result, String regex) {
        if (entryPath.isEmpty()) {
            return -1;
        }

        String[] paths = entryPath.split(regex);
        int deepth = paths.length;
        String path = "";
        String name = "";

        //Get Name and pathEndPos
        int pathEndPos = 0;
        for (int i = deepth - 1; i >= 0; i--) {
            name = paths[i];
            if (name.isEmpty()) {
                continue;
            }
            pathEndPos = i;
            break;
        }

        //Get Path
        for (int i = 0; i < pathEndPos; i++) {
            String tempName = paths[i];
            if (tempName.isEmpty()) {
                continue;
            }
            if (tempName.startsWith("/") || tempName.startsWith("\\")) {
                path = path + tempName;
            } else {
                path = path + "/" + tempName;
            }
        }

        result[0] = path;
        result[1] = name;

        int level = paths.length - 1;
        return level;
    }


    /**
     * 解压压缩文件包
     *
     * @param rootDoc
     * @param doc
     * @return
     */
    protected Doc checkAndExtractEntryFromCompressDoc(Doc rootDoc, Doc doc) {
        Doc parentCompressDoc = getParentCompressDoc(rootDoc, doc);
        if (parentCompressDoc.getId().equals(rootDoc.getId())) {
            //如果doc的parentCompressDoc是rootDoc，那么直接从rootDoc解压出doc
            parentCompressDoc = rootDoc;
        } else {
            //如果doc的parentCompressDoc不存在，那么有两种可能：没有被解压出来，或者是目录（但尾缀是压缩文件尾缀）
            File parentFile = new File(parentCompressDoc.getPath() + parentCompressDoc.getName());
            if (parentFile.exists() == false) {
                //此时无法区分该parentCompressDoc是否是目录，只能将其解压出来，然后让extractEntryFromCompressFile来找到真正的parentCompressDoc
                checkAndExtractEntryFromCompressDoc(rootDoc, parentCompressDoc);
            } else if (parentFile.isDirectory()) {
                //表明parentCompressDoc是目录，因此需要继续向上找到真正的parentCompressDoc
                parentCompressDoc = checkAndExtractEntryFromCompressDoc(rootDoc, parentCompressDoc);
            }
        }

        //解压zipDoc (parentCompressDoc必须已存在，无论是目录还是文件，如果是目录的话则继续向上查找，但此时肯定都存在)
        extractEntryFromCompressFile(rootDoc, parentCompressDoc, doc);
        return parentCompressDoc;
    }

    /**
     * 解压压缩文件
     *
     * @param rootDoc
     * @param parentCompressDoc
     * @param doc
     * @return
     */
    private boolean extractEntryFromCompressFile(Doc rootDoc, Doc parentCompressDoc, Doc doc) {
        parentCompressDoc = checkAndGetRealParentCompressDoc(rootDoc, parentCompressDoc);
        if (parentCompressDoc == null) {
            System.out.println("extractEntryFromCompressFile() " + parentCompressDoc + " is null");
            return false;
        }

        String compressFileType = getCompressFileType(parentCompressDoc.getName());
        if (compressFileType == null) {
            System.out.println("extractEntryFromCompressFile() " + rootDoc.getName() + " 不是压缩文件！");
            return false;
        }

        switch (compressFileType) {
            case "zip":
            case "war":
                return extractEntryFromZipFile(rootDoc, parentCompressDoc, doc);
//            case "rar":
//                return extractEntryFromRarFile(repos, rootDoc, parentCompressDoc, doc);
//            case "7z":
//                return extractEntryFrom7zFile(repos, rootDoc, parentCompressDoc, doc);
//            case "tar":
//                return extractEntryFromTarFile(repos, rootDoc, parentCompressDoc, doc);
//            case "tgz":
//            case "tar.gz":
//                return extractEntryFromTgzFile(repos, rootDoc, parentCompressDoc, doc);
//            case "txz":
//            case "tar.xz":
//                return extractEntryFromTxzFile(repos, rootDoc, parentCompressDoc, doc);
//            case "tbz2":
//            case "tar.bz2":
//                return extractEntryFromTarBz2File(repos, rootDoc, parentCompressDoc, doc);
//            case "gz":
//                return extractEntryFromGzFile(repos, rootDoc, parentCompressDoc, doc);
//            case "xz":
//                return extractEntryFromXzFile(repos, rootDoc, parentCompressDoc, doc);
//            case "bz2":
//                return extractEntryFromBz2File(repos, rootDoc, parentCompressDoc, doc);
        }
        return false;
    }

    /**
     * 解压文件
     *
     * @param rootDoc
     * @param parentCompressDoc
     * @return
     */
    private Doc checkAndGetRealParentCompressDoc(Doc rootDoc, Doc parentCompressDoc) {
        File parentFile = new File(parentCompressDoc.getPath());
        if (parentFile.exists() == false) {
            System.out.println("extractEntryFromCompressFile() parentCompressDoc 不存在！");
            return null;
        }

        if (parentFile.isDirectory()) {
            System.out.println("extractEntryFromCompressFile() parentCompressDoc 是目录，向上层查找realParentCompressDoc！");
            Doc parentParentCompressDoc = getParentCompressDoc(rootDoc, parentCompressDoc);
            return checkAndGetRealParentCompressDoc(rootDoc, parentParentCompressDoc);
        }
        return parentCompressDoc;
    }

    /**
     * 解压压缩包文件
     *
     * @param rootDoc
     * @param parentZipDoc
     * @param zipDoc
     * @return
     */
    private boolean extractEntryFromZipFile(Doc rootDoc, Doc parentZipDoc, Doc zipDoc) {
        boolean ret = false;

        ZipFile parentZipFile = null;
        try {
            parentZipFile = new ZipFile(new File(parentZipDoc.getPath()), "gbk");
            String path = zipDoc.getPath().replace(parentZipDoc.getPath() + "/", "");
            ZipEntry entry = parentZipFile.getEntry(path);
            if (entry == null) {
                return false;
            }

            if (entry.isDirectory()) {
                File dir = new File(zipTmpPath + File.separator + zipDoc.getName());
                return dir.mkdirs();
            }

            //注意即使是目录也要生成目录，因为该目录将是用来区分名字压缩尾缀的目录和真正的压缩文件
            File zipDocParentDir = new File(zipTmpPath + File.separator + path.replace("/" + zipDoc.getName(), ""));
            if (zipDocParentDir.exists() == false) {
                zipDocParentDir.mkdirs();
            }
            String dumpPath = zipTmpPath + File.separator + path;
            ret = dumpZipEntryToFile(parentZipFile, entry, dumpPath);
            zipDoc.setViewPath(dumpPath);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (parentZipFile != null) {
                try {
                    parentZipFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return ret;
    }

    private boolean dumpZipEntryToFile(ZipFile zipFile, ZipEntry entry, String filePath) {
        boolean ret = false;
        int bufSize = 4096;
        byte[] buf = new byte[bufSize];
        int readedBytes;

        File file = new File(filePath);

        FileOutputStream fileOutputStream = null;
        InputStream inputStream = null;
        try {
            fileOutputStream = new FileOutputStream(file);
            inputStream = zipFile.getInputStream(entry);

            while ((readedBytes = inputStream.read(buf)) > 0) {
                fileOutputStream.write(buf, 0, readedBytes);
            }
            ret = true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        return ret;
    }

    //获取doc的parentZipDoc(这里有风险parentZipDoc里面的目录的名字带压缩后缀)
    protected Doc getParentCompressDoc(Doc rootDoc, Doc doc) {
        Doc parentDoc = new Doc();
        String[] temp = new String[2];
        seperatePathAndName(doc.getPath(), temp);

        String s = temp[0];
        if (s.endsWith("/")) {
            s = s.substring(0, s.length() - 1);
        }

        parentDoc.setPath(s);
        parentDoc.setName(temp[1]);
        parentDoc.setId(buildDocIdByName(parentDoc.getPath()));

        if (parentDoc.getId().equals(rootDoc.getId())) {
            return rootDoc;
        }

        if (isCompressFile(parentDoc.getName()) == false) {
            return getParentCompressDoc(rootDoc, parentDoc);
        }

        return parentDoc;
    }

    protected boolean isCompressFile(String name) {
        String fileSuffix = getFileSuffix(name);
        return isZip(fileSuffix);
    }

    protected static boolean isZip(String fileSuffix) {
        if (fileSuffix == null) {
            //"未知文件类型"
            return false;
        }

        switch (fileSuffix) {
            case "zip":
            case "war":
            case "rar":
            case "7z":
            case "tar":
            case "tgz":
            case "gz":
            case "txz":
            case "xz":
            case "bz2":
            case "tbz2":
                return true;
            default:
                break;
        }
        return false;
    }

    /**
     * 处理压缩文件内子文件列表
     *
     * @param rootDoc
     * @param path
     * @param name
     * @return
     */
    protected List<Doc> getZipSubDocList(Doc rootDoc, String path, String name) {
        if (name != null && !name.equals(rootDoc.getName())) {
            System.out.println("getZipSubDocList() 目前不支持对压缩文件的子目录的文件列表");
            return null;
        }

        String compressFileType = getCompressFileType(rootDoc.getName());
        if (compressFileType == null) {
            System.out.println("getZipSubDocList() " + rootDoc.getName() + " 不是压缩文件！");
            return null;
        }

        switch (compressFileType) {
            case "zip":
            case "war":
                return getSubDocListForZip(rootDoc, path, name);
            case "rar":
                return getSubDocListForRar(rootDoc, path, name);
            case "7z":
                return getSubDocListFor7z(rootDoc, path, name);
            case "tar":
                return getSubDocListForTar(rootDoc, path, name);
            case "tgz":
            case "tar.gz":
                return getSubDocListForTgz(rootDoc, path, name);
        }
        return null;
    }

    /**
     * 获取压缩文件类型
     *
     * @param name
     * @return
     */
    protected String getCompressFileType(String name) {
        String fileSuffix = getFileSuffix(name);
        if (fileSuffix == null) {
            //"未知文件类型"
            return null;
        }

        switch (fileSuffix) {
            case "zip":
            case "war":
            case "rar":
            case "7z":
            case "tar":
            case "tgz":
            case "txz":
            case "tbz2":
                return fileSuffix;
            case "gz":
                int pos = name.toLowerCase().lastIndexOf(".tgz") + 4;
                if (pos == name.length()) {
                    return "tgz";
                }
                pos = name.toLowerCase().lastIndexOf(".tar.gz") + 7;
                if (pos == name.length()) {
                    return "tar.gz";
                }
                return fileSuffix;
            case "xz":
                int pos1 = name.toLowerCase().lastIndexOf(".txz") + 4;
                if (pos1 == name.length()) {
                    return "txz";
                }
                pos1 = name.toLowerCase().lastIndexOf(".tar.xz") + 7;
                if (pos1 == name.length()) {
                    return "tar.xz";
                }
                return fileSuffix;
            case "bz2":
                int pos2 = name.toLowerCase().lastIndexOf(".tbz2") + 5;
                if (pos2 == name.length()) {
                    return "tgz";
                }
                pos2 = name.toLowerCase().lastIndexOf(".tar.bz2") + 8;
                if (pos2 == name.length()) {
                    return "tar.bz2";
                }
                return fileSuffix;
            default:
                return null;
        }
    }

    /**
     * 获取压缩文件zip格式的子文件列表
     *
     * @param rootDoc
     * @param path
     * @param name
     * @return
     */
    private List<Doc> getSubDocListForZip(Doc rootDoc, String path, String name) {
        String zipFilePath = rootDoc.getPath();
        String rootPath = rootDoc.getPath() + "/";
        ZipFile zipFile = null;
        List<Doc> subDocList = new ArrayList<Doc>();
        try {
            zipFile = new ZipFile(new File(zipFilePath), "gbk");

            for (Enumeration<ZipEntry> entries = zipFile.getEntries(); entries.hasMoreElements(); ) {
                ZipEntry entry = entries.nextElement();
                String subDocPath = rootPath + entry.getName();
                if (subDocPath.endsWith("/")) {
                    subDocPath = subDocPath.substring(0, subDocPath.lastIndexOf("/"));
                }
                Doc subDoc = new Doc();
                String[] temp = new String[2];
                seperatePathAndName(subDocPath, temp);
                subDoc.setPath(subDocPath);
                subDoc.setName(temp[1]);
                subDoc.setType(entry.isDirectory() ? 2 : 1);
                subDoc.setId(buildDocIdByName(subDocPath));
                subDoc.setPid(buildDocIdByName(temp[0]));
                subDocList.add(subDoc);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (zipFile != null) {
                try {
                    zipFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return subDocList;
    }

    /**
     * 获取压缩文件rar格式的子文件列表
     *
     * @param rootDoc
     * @param path
     * @param name
     * @return
     */
    private List<Doc> getSubDocListForRar(Doc rootDoc, String path, String name) {
        String zipFilePath = rootDoc.getPath();
        String rootPath = rootDoc.getPath() + "/";
        File file = new File(zipFilePath);
        Archive archive = null;
        OutputStream outputStream = null;
        List<Doc> subDocList = new ArrayList<Doc>();
        try {
            archive = new Archive(new FileInputStream(file));
            FileHeader entry;
            while ((entry = archive.nextFileHeader()) != null) {
                String fileName = StringUtils.isBlank(entry.getFileNameW()) ? entry.getFileNameString() : entry.getFileNameW();
                String subDocPath = rootPath + fileName.replace("\\", "/");
                if (subDocPath.endsWith("/")) {
                    subDocPath = subDocPath.substring(0, subDocPath.lastIndexOf("/"));
                }
                Doc subDoc = new Doc();
                String[] temp = new String[2];
                seperatePathAndName(subDocPath, temp);
                subDoc.setPath(subDocPath);
                subDoc.setName(temp[1]);
                subDoc.setType(entry.isDirectory() ? 2 : 1);
                subDoc.setId(buildDocIdByName(subDocPath));
                String s = temp[0];
                if (s.endsWith("/")) {
                    s = s.substring(0, s.length() - 1);
                }
                subDoc.setPid(buildDocIdByName(s));
                subDocList.add(subDoc);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (archive != null) {
                    archive.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return subDocList;
    }

    /**
     * 获取压缩文件7z格式的子文件列表
     *
     * @param rootDoc
     * @param path
     * @param name
     * @return
     */
    private List<Doc> getSubDocListFor7z(Doc rootDoc, String path, String name) {
        String zipFilePath = rootDoc.getPath();
        String rootPath = rootDoc.getPath() + "/";
        File file = new File(zipFilePath);
        List<Doc> subDocList = new ArrayList<Doc>();
        HashMap<Long, Doc> subDocHashMap = new HashMap<Long, Doc>();

        SevenZFile sevenZFile = null;
        OutputStream outputStream = null;
        try {
            sevenZFile = new SevenZFile(file);

            SevenZArchiveEntry entry;
            while ((entry = sevenZFile.getNextEntry()) != null) {
                String subDocPath = rootPath + entry.getName();
                if (subDocPath.endsWith("/")) {
                    subDocPath = subDocPath.substring(0, subDocPath.lastIndexOf("/"));
                }
                Doc subDoc = new Doc();
                String[] temp = new String[2];
                seperatePathAndName(subDocPath, temp);
                subDoc.setPath(subDocPath);
                subDoc.setName(temp[1]);
                subDoc.setType(entry.isDirectory() ? 2 : 1);
                subDoc.setId(buildDocIdByName(subDocPath));
                String s = temp[0];
                if (s.endsWith("/")) {
                    s = s.substring(0, s.length() - 1);
                }
                subDoc.setPid(buildDocIdByName(s));
                subDocList.add(subDoc);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (sevenZFile != null) {
                    sevenZFile.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return subDocList;
    }

    /**
     * 获取压缩文件tar格式的子文件列表
     *
     * @param rootDoc
     * @param path
     * @param name
     * @return
     */
    private List<Doc> getSubDocListForTar(Doc rootDoc, String path, String name) {
        String zipFilePath = rootDoc.getPath();
        String rootPath = rootDoc.getPath() + "/";
        File file = new File(zipFilePath);
        List<Doc> subDocList = new ArrayList<Doc>();
        FileInputStream fis = null;
        OutputStream fos = null;
        TarInputStream tarInputStream = null;
        try {
            fis = new FileInputStream(file);
            tarInputStream = new TarInputStream(fis, 1024 * 2);

            TarEntry entry = null;
            while (true) {
                entry = tarInputStream.getNextEntry();
                if (entry == null) {
                    break;
                }
                String subDocPath = rootPath + entry.getName();
                if (subDocPath.endsWith("/")) {
                    subDocPath = subDocPath.substring(0, subDocPath.lastIndexOf("/"));
                }
                Doc subDoc = new Doc();
                String[] temp = new String[2];
                seperatePathAndName(subDocPath, temp);
                subDoc.setPath(subDocPath);
                subDoc.setName(temp[1]);
                subDoc.setType(entry.isDirectory() ? 2 : 1);
                subDoc.setId(buildDocIdByName(subDocPath));
                subDoc.setPid(buildDocIdByName(temp[0]));
                subDocList.add(subDoc);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
                if (fos != null) {
                    fos.close();
                }
                if (tarInputStream != null) {
                    tarInputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return subDocList;
    }

    /**
     * 获取压缩文件tgz格式的子文件列表
     *
     * @param rootDoc
     * @param path
     * @param name
     * @return
     */
    private List<Doc> getSubDocListForTgz(Doc rootDoc, String path, String name) {
        String zipFilePath = rootDoc.getPath();
        String rootPath = rootDoc.getPath() + "/";
        File file = new File(zipFilePath);
        List<Doc> subDocList = new ArrayList<Doc>();

        FileInputStream fileInputStream = null;
        BufferedInputStream bufferedInputStream = null;
        GZIPInputStream gzipIn = null;
        TarInputStream tarIn = null;
        OutputStream out = null;
        try {
            fileInputStream = new FileInputStream(file);
            bufferedInputStream = new BufferedInputStream(fileInputStream);
            gzipIn = new GZIPInputStream(bufferedInputStream);
            tarIn = new TarInputStream(gzipIn, 1024 * 2);

            TarEntry entry = null;
            while (true) {
                entry = tarIn.getNextEntry();
                if (entry == null) {
                    break;
                }
                //tgz文件中的name可能带./需要预处理
                String entryPath = entry.getName();

                if (entryPath.indexOf("./") == 0) {
                    if (entryPath.length() == 2) {
                        continue;
                    }
                    entryPath = entryPath.substring(2);
                }
                String subDocPath = rootPath + entryPath;
                if (subDocPath.endsWith("/")) {
                    subDocPath = subDocPath.substring(0, subDocPath.lastIndexOf("/"));
                }
                Doc subDoc = new Doc();
                String[] temp = new String[2];
                seperatePathAndName(subDocPath, temp);
                subDoc.setPath(subDocPath);
                subDoc.setName(temp[1]);
                subDoc.setType(entry.isDirectory() ? 2 : 1);
                subDoc.setId(buildDocIdByName(subDocPath));
                subDoc.setPid(buildDocIdByName(temp[0]));
                subDocList.add(subDoc);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (tarIn != null) {
                    tarIn.close();
                }
                if (gzipIn != null) {
                    gzipIn.close();
                }
                if (bufferedInputStream != null) {
                    bufferedInputStream.close();
                }
                if (fileInputStream != null) {
                    fileInputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return subDocList;
    }

}
